﻿using System;
using System.Collections.Generic;
using System.Drawing;

namespace Model
{
	public class Environment
	{

		private static Preferences preferences;
		public static Preferences Preferences
		{
			get { return preferences; }
			set { preferences = value; }
		}

		private static Dictionary<string, CellDefinition> cellDefinitions = new Dictionary<string, CellDefinition>();
		public static Dictionary<string, CellDefinition> CellDefinitions
		{
			get { return cellDefinitions; }
			set { cellDefinitions = value; }
		}

		private static Cell[,] cells;
		public static Cell[,] Cells
		{
			get { return cells; }
			set { cells = value; }
		}

		private static Trajectory trajectory = new Trajectory();
		public static Trajectory Trajectory
		{
			get { return trajectory; }
			set { trajectory = value; }
		}

		public static bool evaluateExpression(Cell cell, string cellDefName, string comp, object rightSide)
		{
			CellDefinition cellDef = cellDefinitions[cellDefName];
			int numberOfCellDefs = CountCellDefsInEnvironment(cell, cellDef);

			double matcher = Double.Parse((string)rightSide);

			bool returnBool = false;
			switch (comp)
			{
				case "<":
					returnBool = numberOfCellDefs < matcher;
					break;
				case "=":
					returnBool = numberOfCellDefs == matcher;
					break;
				case ">":
					returnBool = numberOfCellDefs > matcher;
					break;
				default:
					break;
			}
			return returnBool;
		}

		private static int CountCellDefsInEnvironment(Cell cell, CellDefinition searchedDef)
		{
			int counter = 0;
			Point currentPoint = cell.Position;
			int x = currentPoint.X;
			int y = currentPoint.Y;
			Point xSourroundings = GetXSorroundings(x);
			Point ySourroundings = GetYSorroundings(y);
			switch (preferences.EnvironmentType)
			{

				case EnvironmentType.VonNeumann:
					if (PositionIsOfType(searchedDef, xSourroundings.X, y))
						counter++;
					if (PositionIsOfType(searchedDef, xSourroundings.Y, y))
						counter++;
					if (PositionIsOfType(searchedDef, x, ySourroundings.X))
						counter++;
					if (PositionIsOfType(searchedDef, x, ySourroundings.Y))
						counter++;
					break;

				case EnvironmentType.Moore:
					if (PositionIsOfType(searchedDef, xSourroundings.X, y))
						counter++;
					if (PositionIsOfType(searchedDef, xSourroundings.Y, y))
						counter++;
					if (PositionIsOfType(searchedDef, x, ySourroundings.X))
						counter++;
					if (PositionIsOfType(searchedDef, x, ySourroundings.Y))
						counter++;

					if (PositionIsOfType(searchedDef, xSourroundings.X, ySourroundings.X))
						counter++;
					if (PositionIsOfType(searchedDef, xSourroundings.X, ySourroundings.Y))
						counter++;
					if (PositionIsOfType(searchedDef, xSourroundings.Y, ySourroundings.X))
						counter++;
					if (PositionIsOfType(searchedDef, xSourroundings.Y, ySourroundings.Y))
						counter++;
					break;
				default:
					break;
			}
			return counter;
		}

		private static Point GetYSorroundings(int y)
		{
			Point result = new Point();
			if (y == 0)
			{
				result.X = 1;
				result.Y = cells.GetLength(1) - 1;
			}
			else
			{

				if (y == cells.GetLength(1) - 1)
				{
					result.X = 0;
					result.Y = cells.GetLength(1) - 2;
				}
				else
				{
					result.X = y - 1;
					result.Y = y + 1;
				}
			}

			return result;
		}

		private static Point GetXSorroundings(int x)
		{
			Point result = new Point();
			if (x == 0)
			{
				result.X = 1;
				result.Y = cells.GetLength(0) - 1;
			}
			else
			{

				if (x == cells.GetLength(0) - 1)
				{
					result.X = 0;
					result.Y = cells.GetLength(0) - 2;
				}
				else
				{
					result.X = x - 1;
					result.Y = x + 1;
				}
			}

			return result;
		}

		private static bool PositionIsOfType(CellDefinition cellDef, int x, int y)
		{
			return cells[x, y].CellDefinition.Equals(cellDef);
		}

		public static void initializeEnvironment()
		{
			throw new NotImplementedException();
		}
	}
}
